commonlibsse_ng\rel\id/
relocation_id.rs

1use core::num::NonZeroUsize;
2
3use crate::rel::{ResolvableAddress, id::id_database::DataBaseError};
4
5/// Represents an ID that varies based on runtime format.
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct RelocationID {
8    se_id: u64,
9    ae_id: u64,
10    vr_id: u64,
11}
12
13impl RelocationID {
14    /// Creates a new RelocationID instance.
15    #[inline]
16    pub const fn new(se_id: u64, ae_id: u64, vr_id: u64) -> Self {
17        Self { se_id, ae_id, vr_id }
18    }
19
20    /// Creates a new RelocationID instance.
21    ///
22    /// Used when vr and se take the same ID.
23    #[inline]
24    pub const fn from_se_ae_id(se_vr_id: u64, ae_id: u64) -> Self {
25        Self { se_id: se_vr_id, ae_id, vr_id: se_vr_id }
26    }
27
28    /// Retrieves the appropriate ID based on the runtime format.
29    ///
30    /// # Errors
31    /// Returns an error if the module is in an invalid state.
32    #[inline]
33    pub fn id(&self) -> Result<u64, crate::rel::module::ModuleStateError> {
34        use crate::rel::module::{ModuleState, Runtime};
35
36        let runtime = ModuleState::map_or_init(|module| module.runtime)?; // derived Copy
37
38        Ok(match runtime {
39            Runtime::Ae => self.ae_id,
40            Runtime::Se => self.se_id,
41            Runtime::Vr => self.vr_id,
42        })
43    }
44}
45
46impl ResolvableAddress for RelocationID {
47    #[inline]
48    fn offset(&self) -> Result<NonZeroUsize, DataBaseError> {
49        use crate::rel::id::id_database::ID_DATABASE;
50        ID_DATABASE.id_to_offset(self.id()?)
51    }
52}
53
54#[cfg(feature = "test_on_local")]
55#[cfg(test)]
56mod local_tests {
57    use super::*;
58
59    // REQUIREMENT: We need the version of AddressLibrary specified in Skyrim's Data on Steam.
60    #[test]
61    fn test_relocation() {
62        let relocation = RelocationID::from_se_ae_id(514287, 400447); // Calender::get_singleton() -> *mut Calender
63        if let (Ok(offset), Ok(address)) = (relocation.offset(), relocation.address()) {
64            dbg!(offset, &address); // AE offset(ver. 1.6.1170.0): 34572640
65        }
66    }
67}